﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using G.Web;
using G.Net;
using Microsoft.Phone.Controls;
using System.Globalization;
using System.IO;
using System.Text;
using System.Collections.ObjectModel;
using G.Net.Oauth;
using System.Text.RegularExpressions;

namespace G.WeiBo.WebAPI
{
    public class DefaultClient
    {
        //private const string REQUEST_TOKEN = "oauth/request_token";
        //private const string AUTHORIZE = "oauth/authorize";
        //private const string ACCESS_TOKEN = "oauth/access_token";

        //OauthClient oauthClient;
        //WebUtil webutil;
        #region DefaultTopClient Constructors

        /// <summary>
        /// 使用AppConfiguration中配置来初始化
        /// </summary>
        public DefaultClient()
        {
            //oauthClient = new OauthClient();
            //webutil = new WebUtil();
        }

        #endregion

        private void DoResponse<T>(WebExceptionStatus status, string msg, Action<T> callBack) where T : ResponseData
        {
            if (status == WebExceptionStatus.Success)
            {
                ParseToObj<T>(msg, callBack);
            }
            else
            {

                //G.Net.Oauth.Oauth2Valid.RefreshToken(APIConfig.AppName, c =>
                //{
                //    var aa = c;
                //});

                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    G.Navigate.PhoneApplicationPageHelp.GetBasePage().ShowState(string.Format("{0}:{1}", status.ToString(), msg));
                });
                T rsp = Activator.CreateInstance<T>();
                rsp.Error = string.Format("{0}:{1}", status.ToString(), msg);
                rsp.Body = msg;
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    callBack(rsp);
                });

            }
        }

        public void Execute<T>(IRequest<T> request, Action<T> callBack) where T : ResponseData
        {
            Execute<T>(request, null, callBack);
        }
        private Dictionary<string, string> ParseQueryString(string str)
        {
            string[] strs = str.Split('&');
            Dictionary<string, string> dics = new Dictionary<string, string>();

            foreach (var item in strs)
            {
                string[] keyValue = item.Split('=');
                if (keyValue.Length == 2)
                    dics.Add(keyValue[0], keyValue[1]);
            }
            return dics;
        }
        OAuth2AccessToken OAuth2AccessToken;
        public void Execute<T>(IRequest<T> request, string session, Action<T> callBack) where T : ResponseData
        {
            //if (OAuth2AccessToken == null){
            //    G.Net.Oauth.Oauth2Valid.Valid("sina", (c =>
            //    {
            //        Execute(request, callBack);
            //    }));
            //    return;
            //}

            // 是否需要上传文件
            if (request is IUploadRequest<T>)
            {
                OauthFilePost fPost = new OauthFilePost(string.Format("{0}/{1}", APIConfig.BaseUrl, request.GetURL()));
                foreach (var item in request.GetParameters())
                {
                    fPost.Params.Add(item.Key, item.Value);
                }
                fPost.FileBuffer = (request as IUploadRequest<T>).UploadData;
                fPost.Request((s, msg) =>
                {
                    DoResponse<T>(s, msg, callBack);
                });
            }
            else
            {
                if (request.HttpMethod() == G.Net.HttpMethod.Get)
                {
                    G.Net.Oauth.Oauth2HttpGet req = new Net.Oauth.Oauth2HttpGet(string.Format("{0}/{1}", APIConfig.BaseUrl, request.GetURL()));
                    foreach (var item in request.GetParameters())
                    {
                        req.Params.Add(item.Key, item.Value);
                    }
                    req.Params.Add("t", DateTime.Now.GetTimestamp().ToString());
                    req.Request((s, msg) =>
                    {
                        DoResponse<T>(s, msg, callBack);
                    });
                }
                else if (request.HttpMethod() == G.Net.HttpMethod.Post)
                {
                    G.Net.Oauth.Oauth2HttpPost req = new Oauth2HttpPost(string.Format("{0}/{1}", APIConfig.BaseUrl, request.GetURL()));
                    foreach (var item in request.GetParameters())
                    {
                        req.Params.Add(item.Key, item.Value);
                    }
                    req.Params.Add("t", DateTime.Now.GetTimestamp().ToString());
                    req.Request((s, msg) =>
                    {
                        DoResponse<T>(s, msg, callBack);
                    });
                }

            }
        }

        //JsonParser jsonParser = new JsonParser();
        private void ParseToObj<T>(string body, Action<T> callBack) where T : ResponseData
        {
            T rsp = null;
            //if (body.StartsWith("exception"))
            //{
            //    rsp = Activator.CreateInstance<T>();
            //    rsp.IsError = true;
            //    string[] strs = body.Split(':');
            //    rsp.Body = string.Format("{0}\r\n{1}", strs[1], strs[2]);
            //    if (callBack.Target is UIElement)
            //    {
            //        (callBack.Target as UIElement).Dispatcher.BeginInvoke(() =>
            //        {
            //            MessageBox.Show(rsp.Body, "出Bug啦！", MessageBoxButton.OK);
            //        });
            //    }
            //    callBack(rsp);
            //    return;
            //}
            try
            {
                Type t = typeof(T);
                if (t.IsGenericType && t.IsSubclassOf(typeof(ResponseData)))
                {
                    var gType = t.GetGenericArguments();
                    if (gType.Length > 1)
                        throw new InvalidOperationException("不支持超过两个类型的泛型");
                    var obj = G.Utils.SerializerHelp.JsonDeserialize(body, gType[0]);
                    rsp = Activator.CreateInstance<T>();
                    t.GetProperty("Response").SetValue(rsp, obj, null);
                }
                else
                {
                    rsp = G.Utils.SerializerHelp.JsonDeserialize<T>(body);// jsonParser.Parse<T>(body);
                }

                //JsonSerializerPathAttribute att = Attribute.GetCustomAttribute(typeof(T), typeof(JsonSerializerPathAttribute)) as JsonSerializerPathAttribute;
                //if (att == null)
                //{
                //    //rsp = jsonParser.Parse<T>(body);
                //}
                //else
                //{
                //    //object obj = jsonParser.Parse(att.PropertyType, body);
                //    //rsp = Activator.CreateInstance<T>();
                //    //typeof(T).GetProperty(att.PropertyName).SetValue(rsp, obj, null);
                //}
                rsp.Body = body;
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    callBack(rsp);
                });
            }
            catch (Exception ex)
            {
                if (callBack.Target is UIElement)
                {
                    (callBack.Target as UIElement).Dispatcher.BeginInvoke(() =>
                    {
                        MessageBox.Show(ex.Message, "数据解析出错！", MessageBoxButton.OK);
                    });
                }
                if (rsp == null)
                {
                    rsp = Activator.CreateInstance<T>();
                }
                rsp.Error = "数据解析出错" + ex.Message;
                rsp.Body = body;
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    callBack(rsp);
                });
            }

        }



        //private void GetRequestToken(Action<OAuthRequestToken> callback)
        //{
        //    var requester = new TokenObtainRequest("http://api.t.sina.com.cn/oauth/request_token");
        //    requester.Request((status, msg) =>
        //    {
        //        if (status == WebExceptionStatus.Success)
        //        {
        //            var match = Regex.Match(msg, APIConfig.RetrieveRequestTokenPattern, RegexOptions.IgnoreCase);
        //            if (!match.Success)
        //                throw new Exception("Failed to retrieve request token from the web response.");
        //            var requestToken = match.Groups[1].Value;
        //            var requestTokenSecret = match.Groups[2].Value;
        //            callback(new OAuthRequestToken() { Token = match.Groups[1].Value, Secret = match.Groups[2].Value });
        //        }
        //        else
        //            callback(null);
        //    });
        //}

        //public void Authorize(Action<string> callback, string requestToken, string userName, string password)
        //{
        //    var requester = new HttpGet("http://api.t.sina.com.cn/oauth/authorize");
        //    requester.Params.Add(Constants.OAuthToken, requestToken);
        //    requester.Params.Add("userId", OAuthEncoder.UrlEncode(userName));
        //    requester.Params.Add("passwd", OAuthEncoder.UrlEncode(password));
        //    requester.Params.Add(Constants.OAuthCallback, "xml");

        //    requester.Request((status, msg) =>
        //    {
        //        if (status == WebExceptionStatus.Success)
        //        {
        //            var match = Regex.Match(msg, APIConfig.RetrieveAuthorizationCodePattern, RegexOptions.CultureInvariant);
        //            if (match.Success)
        //                callback(match.Groups[1].Value);
        //            else
        //                throw new Exception("Invalid user name or password.");
        //        }
        //        else
        //            callback(null);
        //    });
        //}

        //private void GetAccessToken(Action<OAuthAccessToken> callback, OAuthRequestToken requestToken, string verifier)
        //{
        //    var requester = new TokenObtainRequest("http://api.t.sina.com.cn/oauth/access_token");
        //    requester.Params.Add(new ParamPair(Constants.OAuthToken, requestToken.Token));
        //    requester.Params.Add(new ParamPair(Constants.OAuthVerifier, verifier));
        //    requester.Secret = requestToken.Secret;
        //    requester.Request((status, msg) =>
        //    {
        //        if (status == WebExceptionStatus.Success)
        //        {
        //            var accessTokenMatch = Regex.Match(msg, APIConfig.RetrieveAccessTokenPattern, RegexOptions.IgnoreCase);
        //            if (!accessTokenMatch.Success)
        //                throw new Exception("Failed to retrieve access token.");
        //            var accessToken = accessTokenMatch.Groups[1].Value;
        //            var accessTokenSecret = accessTokenMatch.Groups[2].Value;
        //            var userID = accessTokenMatch.Groups[4].Value;
        //            callback(new OAuthAccessToken() { Token = accessToken, Secret = accessTokenSecret, UserID = userID });
        //        }
        //        else
        //            callback(null);
        //    });
        //}
        ///// <summary>
        ///// 登录
        ///// </summary>
        ///// <param name="callback"></param>
        ///// <param name="userName"></param>
        ///// <param name="password"></param>
        //public void Login(Action<OAuthAccessToken> callback, string userName, string password)
        //{
        //    GetRequestToken((token) =>
        //    {
        //        if (token != null)
        //        {
        //            Authorize((verify) =>
        //            {
        //                if (verify != null)
        //                {
        //                    GetAccessToken(callback, token, verify);
        //                }
        //                else
        //                    callback(null);
        //            }, token.Token, userName, password);
        //        }
        //        else
        //            callback(null);
        //    });
        //}
    }
}
